#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->lineEdit->setText("127.0.0.1");
    ui->lineEdit_2->setText("8099");

    this->searchAvailablePorts();

    serial = new QSerialPort();
    socket = new QTcpSocket();

    // 连接信号与槽
    connect(serial, &QSerialPort::readyRead, this, &MainWindow::handleReadyRead);
    connect(serial, &QSerialPort::errorOccurred, this, &MainWindow::handleError);

    connect(socket, &QTcpSocket::readyRead, this, &MainWindow::tcpReadyRead);
    connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::errorOccurred), this, &MainWindow::tcpError);

}

MainWindow::~MainWindow()
{
    delete ui;
    serial->close();
    socket->disconnectFromHost();
    socket->close();
}

void MainWindow::searchAvailablePorts()
{
    //搜索可用串口
    ui->comboBox->clear();
    ports.clear();
    ports = QSerialPortInfo::availablePorts();
    foreach (const QSerialPortInfo &info, ports) {
        qDebug() << "Name        : " << info.portName();
        ui->comboBox->addItem(info.portName());
    }

}

void MainWindow::on_pushButton_3_clicked()
{
    this->searchAvailablePorts();
}

void MainWindow::on_pushButton_2_clicked()
{
    // socket->bind(50000);
    socket->connectToHost(QHostAddress(ui->lineEdit->text()), ui->lineEdit_2->text().toInt());
    if (socket->waitForConnected(3000)) {
        qDebug() << "Connected to server!";
        socket->write("SUBSCRIBE TALLY\r\n");
    } else {
        qDebug() << "Failed to connect to server!";
    }
}

void MainWindow::on_pushButton_clicked()
{
    // serial->setPortName(ui->comboBox->currentText());
    int portIndex = ui->comboBox->currentIndex();
    serial->setPort(ports[portIndex]);
    if (serial->open(QIODevice::ReadWrite)) {
        // 设置波特率、数据位、停止位、校验位
        serial->setBaudRate(QSerialPort::Baud115200);
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);
        qDebug() << serial->portName() << "opened";
        ui->textEdit->insertPlainText(QString("%1 opened.\n").arg(serial->portName()));
    } else {
        qDebug() << "Failed to open port" << serial->portName();
    }

}

void MainWindow::sendData(const QByteArray &data)
{
    qDebug() << data;
    serial->write(data);
}

void MainWindow::handleReadyRead()
{
    QByteArray data = serial->readAll();
    qDebug() << "Received:" << data;
}

void MainWindow::handleError(QSerialPort::SerialPortError error)
{
    if (error != QSerialPort::NoError) {
        qDebug() << "Serial port error:" << serial->errorString();
    }
}

void MainWindow::tcpReadyRead()
{
    QByteArray data = socket->readAll();
    qDebug() << "Received from server:" << data;
    ui->textEdit->insertPlainText(data);
    QByteArray ba;
    QStringList tallyList = getTallyStatus(QString::fromLatin1(data));
    for (int i = 0; i < tallyList.length(); i++) {
        for (QChar ch : tallyList[i]) {
            // 将字符转成数字（0x01, 0x02, ...），并添加到 QByteArray
            uint8_t value = ch.toLatin1() - '0'; // '1' - '0' = 1
            ba.append(value);
        }
        // sendData(ba.toHex());
        sendData(ba);
        ba.clear();
    }
}

void MainWindow::tcpError(QAbstractSocket::SocketError error)
{
    qDebug() << "Socket error:" << socket->errorString();
}

QStringList MainWindow::getTallyStatus(const QString &text)
{
    QStringList tallyList;
    static QRegularExpression re("TALLY OK ([012]+)");
    QRegularExpressionMatchIterator it = re.globalMatch(text);

    while (it.hasNext()) {
        QRegularExpressionMatch match = it.next();
        tallyList.append(match.captured(1));
    }

    return tallyList;
}

void MainWindow::on_pushButton_4_clicked()
{
    if (serial->isOpen()) {
        serial->close();
    }
    qDebug() << serial->portName() << "closed";
    ui->textEdit->insertPlainText(QString("%1 closed.\n").arg(serial->portName()));
}

